﻿// Copyright 2007, 2008 - Ariel Yaroshevich (a.k.a blackrussian) (hamlet@inter.net.il)
// This file is part of SharpMap.
// SharpMap is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// SharpMap is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public License
// along with SharpMap; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using SharpMap.Rendering.Rendering2D;
using System.Windows.Media;
using Smg = SharpMap.Geometries;


namespace SharpMap.Wpf
{
    public class GeometryConverter : IValueConverter
    {
        BasicGeometryRenderer2D<Drawing> _renderer = new BasicGeometryRenderer2D<Drawing>(new SharpMap.Wpf.Rendering.VectorRenderer());
        #region IValueConverter Members
        static SharpMap.Styles.VectorStyle defaultStyle;
        static GeometryConverter()
        {
            defaultStyle = new SharpMap.Styles.VectorStyle();
            defaultStyle.Line = new SharpMap.Styles.StylePen(new SharpMap.Styles.SolidStyleBrush(SharpMap.Styles.StyleColor.Red), 0.2);
            defaultStyle.Outline = new SharpMap.Styles.StylePen(new SharpMap.Styles.SolidStyleBrush(SharpMap.Styles.StyleColor.Black), 0.2);
            SharpMap.Styles.StyleColor clr = SharpMap.Styles.StyleColor.FromBgra(255,0,0,100);
            SharpMap.Styles.SolidStyleBrush b = new SharpMap.Styles.SolidStyleBrush(clr);

            defaultStyle.Fill = b;
        }
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (!typeof(Drawing).IsAssignableFrom(targetType))
                return null;
            SharpMap.Geometries.Geometry sourceGeometry = value as SharpMap.Geometries.Geometry;
            if (sourceGeometry != null)
            {
               
               
                IEnumerable<Drawing> drawings =
                renderGeometries(sourceGeometry, defaultStyle, SharpMap.Rendering.RenderState.Normal);
                
                Drawing retVal = null;
                int nDrawing = 0;
                foreach (Drawing d in drawings)
                {
                    if (nDrawing == 0)
                    {
                        retVal = d;
                        ++nDrawing;
                    }
                    else if (nDrawing == 1)
                    {
                        DrawingGroup g = new DrawingGroup();
                        using (DrawingContext ctx = g.Append())
                        {
                            ctx.DrawDrawing(retVal);
                            ctx.DrawDrawing(d);
                        }
                        retVal = g;
                        ++nDrawing;
                    }
                    else 
                    {
                        using (DrawingContext ctx = ((DrawingGroup)retVal).Append())
                        {
                            ctx.DrawDrawing(d);
                        }
                    }

                    GeoPanel.SetWorldX(retVal, retVal.Bounds.X);
                    GeoPanel.SetWorldY(retVal, retVal.Bounds.Y);
                    return retVal;
                }
            }
            return null;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }


        private IEnumerable<Drawing> renderGeometries(SharpMap.Geometries.Geometry geometry,
            SharpMap.Styles.VectorStyle style, SharpMap.Rendering.RenderState renderState)
        {
            
            if (geometry == null)
                throw new ArgumentNullException("geometry");

            if (geometry is Smg.Polygon)
            {

                return _renderer.DrawPolygon(geometry as Smg.Polygon, style.Fill, style.HighlightFill, style.SelectFill, style.Outline,
                    style.HighlightOutline, style.SelectOutline, renderState);
            }
            else if (geometry is Smg.MultiPolygon)
            {
                return _renderer.DrawMultiPolygon(geometry as Smg.MultiPolygon, style.Fill, style.HighlightFill, style.SelectFill,
                    style.Outline, style.HighlightOutline, style.SelectOutline, renderState);
            }
            else if (geometry is Smg.LineString)
            {
                return _renderer.DrawLineString(geometry as Smg.LineString, style.Line, style.HighlightLine, style.SelectLine,
                    style.Outline, style.HighlightOutline, style.SelectOutline, renderState);
            }
            else if (geometry is Smg.MultiLineString)
            {
                return _renderer.DrawMultiLineString(geometry as Smg.MultiLineString, style.Line, style.HighlightLine, style.SelectLine,
                    style.Outline, style.HighlightOutline, style.SelectOutline, renderState);
            }
            else if (geometry is Smg.Point)
            {
                return _renderer.DrawPoint(geometry as Smg.Point, style.Symbol, style.HighlightSymbol, style.SelectSymbol, renderState);
            }
            else if (geometry is Smg.MultiPoint)
            {
                return _renderer.DrawMultiPoint(geometry as Smg.MultiPoint, style.Symbol, style.HighlightSymbol, style.SelectSymbol, renderState);
            }
            else if (geometry is Smg.GeometryCollection)
            {
                List<Drawing> renderObjects = new List<Drawing>();

                foreach (Smg.Geometry g in (geometry as Smg.GeometryCollection))
                {
                    renderObjects.AddRange(renderGeometries(g, style, renderState));
                }

                return renderObjects;
            }
            else
                throw new ArgumentException("geometry");
        }
        #endregion
    }
}
